﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Bridge.Shared;
using Bridge.Shared.Extensions;
using Bridge.Shared.Models;
using Bridge.Workflow.Application.Contracts;
using Bridge.Workflow.Domain;
using Bridge.Workflow.Extension;
using Bridge.Workflow.Workflow.Dto;
using Bridge.Workflow.WorkflowCore;
using Bridge.Workflow.Workflows.Dtos;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using Nito.AsyncEx;
using Users;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Identity;
using Volo.Abp.Linq;
using Volo.Abp.Uow;
using Volo.Abp.Users;
using WorkflowCore.Models;

namespace Bridge.Workflow.Application
{
    /// <summary>
    /// 工作流审核相关
    /// </summary>
    public class WorkflowAuditService : ApplicationService, IWorkflowAuditService
    {
        private readonly IRepository<PersistedWorkflowAuditor, string> _auditorRepos;
        private readonly IRepository<PersistedWorkflow, string> _workflowRepos;
        private readonly IRepository<PersistedExecutionPointer, string> _pointerRepos;
        private readonly IRepository<PersistedWorkflowDefinition, string> _workflowDefinitionRepos;
        private readonly IAbpWorkflowManager _abpWorkflowManager;
        private readonly ICurrentUser _currentUser;
        private readonly IAsyncQueryableExecuter _asyncQueryableExecuter;
        private readonly IUserService _userService;
        private readonly IUserAppService _userAppService;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="auditorRepos"></param>
        /// <param name="asyncQueryableExecuter"></param>
        /// <param name="abpWorkflowManager"></param>
        /// <param name="currentUser"></param>
        public WorkflowAuditService(
            IRepository<PersistedWorkflowAuditor, string> auditorRepos,
            IRepository<PersistedWorkflow, string> workflowRepos,
            IRepository<PersistedWorkflowDefinition, string> workflowDefinitionRepos,
        IAsyncQueryableExecuter asyncQueryableExecuter,
            IAbpWorkflowManager abpWorkflowManager,
            ICurrentUser currentUser,
            IRepository<PersistedExecutionPointer, string> pointerRepos,
            IUserService userService, IUserAppService userAppService)
        {
            _auditorRepos = auditorRepos;
            _workflowRepos = workflowRepos;
            _workflowDefinitionRepos = workflowDefinitionRepos;
            _asyncQueryableExecuter = asyncQueryableExecuter;
            _currentUser = currentUser;
            _abpWorkflowManager = abpWorkflowManager;
            _pointerRepos = pointerRepos;
            _userService = userService;
            _userAppService = userAppService;
        }

        /// <summary>
        /// 获取我的待审批流程
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<ResponseResult<PagedResultDto<GetMyAuditPageListOutput>>> GetAllAsync(GetMyAuditPageListInput input)
        {
            var query = from a in (await _auditorRepos.GetQueryableAsync())
                        join b in (await _pointerRepos.GetQueryableAsync()) on a.ExecutionPointerId equals b.Id
                        join c in (await _workflowRepos.GetQueryableAsync()) on b.WorkflowId equals c.Id
                        join d in (await _workflowDefinitionRepos.GetQueryableAsync()) on c.WorkflowDefinitionId equals d.Id
                        where ((input.IsAll.HasValue&& input.IsAll.Value)?true: a.UserId == _currentUser.Id) 
                        && a.Status == EnumAuditStatus.UnAudited
                        && (string.IsNullOrEmpty(input.Title) ? true : a.Workflow.Description.Contains(input.Title))
                        && (string.IsNullOrEmpty(input.CreatorName) ? true : a.Workflow.CreateUserIdentityName.Contains(input.CreatorName))
                        && (string.IsNullOrEmpty(input.BeginTime) ? true : a.CreationTime >= Convert.ToDateTime(input.BeginTime))
                        && (string.IsNullOrEmpty(input.EndTime) ? true : a.CreationTime <= Convert.ToDateTime(input.EndTime))
                        orderby a.CreationTime descending
                        select new { a, b, c, d };

            int totalCount = query.Count();
            var myAuditList = query.Skip(input.SkipCount).Take(input.MaxResultCount).ToList();

            var outputList = new List<GetMyAuditPageListOutput>();
            foreach (var item in myAuditList)
            {
           
                GetMyAuditPageListOutput output = new GetMyAuditPageListOutput()
                {
                    Id = item.a.Id,
                    ExecutionPointer = ObjectMapper.Map<PersistedExecutionPointer, ExecutionPointerOutPut>(item.b),
                    CreationTime = item.c.CreationTime,
                    Title = item.c.Description,
                    UserName = item.a.UserIdentityName,
                    WorkflowDefinitionId = item.d.Id,
                    Version = item.d.Version,
                    WorkflowId = item.a.WorkflowId,
                    Status = item.a.Status,
                    AuditTime = item.a.AuditTime,
                    CreatorId = item.a.CreatorId ?? Guid.Empty,
                    CreatorName = item.c.CreateUserIdentityName,
                    Nodes = item.d.Nodes,
                    BusinessData = JsonConvert.DeserializeObject<WorkflowData>(item.c.Data),
                };
                outputList.Add(output);
            }


            var result = new PagedResultDto<GetMyAuditPageListOutput>(totalCount, outputList);

            return ResponseResult<PagedResultDto<GetMyAuditPageListOutput>>.Success(string.Empty, result);
        }
        public async Task<ResponseResult<PagedResultDto<GetMyAuditPageListOutput>>> GetAllAsync_old(GetMyAuditPageListInput input)
        {
            
                var qeury = (await _auditorRepos.GetQueryableAsync())
                .Where(u => u.UserId == _currentUser.Id && u.Status == EnumAuditStatus.UnAudited)
                .WhereIf(!string.IsNullOrEmpty(input.Title), u => u.Workflow.Description.Contains(input.Title))
                .WhereIf(!string.IsNullOrEmpty(input.CreatorName), u => u.Workflow.CreateUserIdentityName.Contains(input.CreatorName))
                 .WhereIf(!string.IsNullOrEmpty(input.BeginTime), u => u.CreationTime >= Convert.ToDateTime(input.BeginTime))
             .WhereIf(!string.IsNullOrEmpty(input.EndTime), u => u.CreationTime <= Convert.ToDateTime(input.EndTime))
             .OrderByDescending(a=>a.CreationTime);
            

            var auditList = qeury.Skip(input.SkipCount).Take(input.MaxResultCount).AsNoTracking();



            var pointerIds = auditList.ToList().Select(a => a.ExecutionPointerId);
            var pointerList = await _pointerRepos.GetListAsync(a => pointerIds.Contains(a.Id));

            var workflowIds = auditList.ToList().Select(a => a.WorkflowId);
            var workflowList = await _workflowRepos.GetListAsync(a => workflowIds.Contains(a.Id));

            var workflowDefIds = workflowList.Select(a => a.WorkflowDefinitionId);
            var workflowDefList =await _workflowDefinitionRepos.GetListAsync(a => workflowDefIds.Contains(a.Id));


            var outputList = new List<GetMyAuditPageListOutput>();
            foreach (var u in auditList)
            {
                var pointer = pointerList.FirstOrDefault(a => a.Id == u.ExecutionPointerId);

                var workflow = workflowList.Where(a => a.Id == u.WorkflowId).FirstOrDefault();

                var workflowDef = workflowDefList.Where(a => a.Id == workflow.WorkflowDefinitionId).FirstOrDefault();
                ExecutionPointerOutPut p = ObjectMapper.Map<PersistedExecutionPointer, ExecutionPointerOutPut>(pointer);
                GetMyAuditPageListOutput output = new GetMyAuditPageListOutput()
                {
                    Id = u.Id,
                    ExecutionPointer = p,
                    CreationTime = workflow.CreationTime,
                    Title = workflow.Description,
                    UserName = u.UserIdentityName,
                    WorkflowDefinitionId = workflowDef.Id,
                    Version = workflowDef.Version,
                    WorkflowId = u.WorkflowId,
                    Status = u.Status,
                    AuditTime = u.AuditTime,
                    CreatorId = u.CreatorId ?? Guid.Empty,
                    CreatorName =workflow.CreateUserIdentityName,
                    Nodes = workflowDef.Nodes,
                    BusinessData = JsonConvert.DeserializeObject<WorkflowData>(workflow.Data),
                };
                outputList.Add(output);
            }
           var result = new PagedResultDto<GetMyAuditPageListOutput>(qeury.Count(), outputList);

            return ResponseResult<PagedResultDto<GetMyAuditPageListOutput>>.Success(string.Empty, result);
        }
        

        /// <summary>
        /// 获取我参与的在途流程
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<ResponseResult<PagedResultDto<GetMyAuditPageListOutput>>> GetProcessingAsync(GetMyAuditPageListInput input)
        {
            var result = await (await _auditorRepos.GetQueryableAsync()).Where(u => (u.UserId == _currentUser.Id) && u.Status == EnumAuditStatus.UnAudited)
             .WhereIf(!string.IsNullOrEmpty(input.Title), u => u.Workflow.Description.Contains(input.Title))
             .WhereIf(!string.IsNullOrEmpty(input.CurrentStepName), u => u.ExecutionPointer.StepName.Contains(input.CurrentStepName))
             .WhereIf(!string.IsNullOrEmpty(input.CreatorName), u => u.Workflow.CreateUserIdentityName.Contains(input.CreatorName))
             .WhereIf(!string.IsNullOrEmpty(input.BeginTime), u => u.CreationTime >= Convert.ToDateTime(input.BeginTime))
             .WhereIf(!string.IsNullOrEmpty(input.EndTime), u => u.CreationTime <= Convert.ToDateTime(input.EndTime))
             .OrderByDescending(u => u.CreationTime).ToPagedResultAsync(input, u => new GetMyAuditPageListOutput()
             {
                 Id = u.Id,
                 //ExecutionPointerId = u.ExecutionPointerId,
                 CreationTime = u.CreationTime,
                 Title = u.Workflow.Description,
                 UserName = u.UserIdentityName,
                 WorkflowDefinitionId = u.Workflow.WorkflowDefinitionId,
                 Version = u.Workflow.WorkflowDefinition.Version,
                 WorkflowId = u.WorkflowId,
                 Status = u.Status,
                 AuditTime = u.AuditTime,
                 CreatorId = u.CreatorId ?? Guid.Empty,
                 //CurrentStepName = u.ExecutionPointer.StepName,
                 BusinessData = JsonConvert.DeserializeObject<WorkflowData>(u.Workflow.Data),
                 CreatorName = u.Workflow.CreateUserIdentityName,
                 IsApproval = u.UserId == _currentUser.Id,
                 Nodes = u.Workflow.WorkflowDefinition.Nodes,
             });
            return ResponseResult<PagedResultDto<GetMyAuditPageListOutput>>.Success(string.Empty, result);
        }

        /// <summary>
        /// 获取详情
        /// </summary>
        /// <param name="input">流程ID</param>
        /// <returns></returns>
        /// 
        public async Task<PageResponseResult<WorkflowAuditRecordOutput>> GetAuditRecordsAsync(string id)
        {
            var query = from a in (await _auditorRepos.GetQueryableAsync()).AsNoTracking()
                        join b in (await _pointerRepos.GetQueryableAsync()).AsNoTracking() on a.ExecutionPointerId equals b.Id
                        where a.WorkflowId== id
                        select new { a, b };
            var totalCount = await query.CountAsync();
            var result = query.ToList();
            var list = result.Select(s=>new WorkflowAuditRecordOutput {
                Title = s.b.StepName,
                AuditTime =s.a.AuditTime,
                Status = EnumExtensions.GetDescription(s.a.Status),
                Remark = s.a.Remark,
                UserIdentityName = s.a.UserIdentityName



            }).ToList();
            return PageResponseResult<WorkflowAuditRecordOutput>.Success("操作成功", list, 1000,0, totalCount);
        }
        public async Task<ResponseResult<WorkflowAuditDto>> GetAuditRecordsAsync_old(string id)
        {
            var query = (await _auditorRepos.GetQueryableAsync()).Where(u => u.WorkflowId == id).Select(u => new
            {
                u.ExecutionPointerId,
                AuditTime = u.AuditTime,
                Status = u.Status,
                Remark = u.Remark,
                UserIdentityName = u.UserIdentityName,
                UserHeadPhoto = u.UserHeadPhoto,
                u.UserId,
            });
            var data = await _asyncQueryableExecuter.ToListAsync(query);
            //审核记录
            var resords = data.GroupBy(i => i.ExecutionPointerId).Select(u => new
            {
                ExecutionPointerId = u.Key,
                AuditRecords = u.Select(i => new WorkflowAuditRecord()
                {
                    UserId = i.UserId,
                    AuditTime = i.AuditTime,
                    Status = i.Status,
                    Remark = i.Remark,
                    UserIdentityName = i.UserIdentityName,
                    UserHeadPhoto = i.UserHeadPhoto,
                })
            }).ToDictionary(i => i.ExecutionPointerId, i => i.AuditRecords);

            return ResponseResult<WorkflowAuditDto>.Success(string.Empty, new WorkflowAuditDto()
            {
                NeedAudit = data.Any(i => i.UserId == _currentUser.Id && i.Status == EnumAuditStatus.UnAudited),
                AuditRecords = resords
            });
        }


        /// <summary>
        /// 修改业务数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<ResponseResult> EditBusinessDataAsync(EditBusinessDataInput input)
        {
            var workflow = await _workflowRepos.FirstOrDefaultAsync(s => s.Id == input.WorkflowId);
            if (workflow == null)
            {
                return ResponseResult.Fail("流程不存在");
            }
            WorkflowData BusinessData = JsonConvert.DeserializeObject<WorkflowData>(workflow?.Data);
            if (!string.IsNullOrEmpty(input.BusinessCode))
            {
                BusinessData.BusinessCode = input.BusinessCode;
            }
            //if (!string.IsNullOrEmpty(input.AgencyId))
            //{
            //    BusinessData.AgencyId = input.AgencyId;
            //}
            if (input.SumPrice > 0)
            {
                BusinessData.SumPrice = input.SumPrice;
            }
            workflow.Data = JsonConvert.SerializeObject(BusinessData);
            await _workflowRepos.UpdateAsync(workflow, true);
            return ResponseResult.Success(string.Empty);
        }
        /// <summary>
        /// 审核
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [UnitOfWork]
        public async Task<ResponseResult> AuditAsync(WorkflowAuditInput input)
        {
            try
            {
                var pointer = await _pointerRepos.FirstOrDefaultAsync(a => a.Id == input.ExecutionPointerId);
                if(pointer == null || pointer.Status != PointerStatus.Running)
                {
                    return ResponseResult.Fail("当前流程已审批！");
                }
                var entity = await _auditorRepos.FirstOrDefaultAsync(u => u.ExecutionPointerId == input.ExecutionPointerId && u.UserId == _currentUser.Id);
                if (entity == null)
                {
                    return ResponseResult.Fail("不需要您审核");
                }

                var workflow = await _workflowRepos.FirstOrDefaultAsync(s => s.Id == entity.WorkflowId);
                if (workflow == null)
                {
                    return ResponseResult.Fail("流程不存在");
                }
                //如果是通过就走正向流程
               var workflowDef = await _workflowDefinitionRepos.FirstOrDefaultAsync(a => a.Id == workflow.WorkflowDefinitionId);
                if(workflowDef == null)
                {
                    return ResponseResult.Fail("流程未定义");
                }

                var options = WorkFlowConfig.LoadConfig(workflowDef.Title);
                if(options == null)
                {
                    return ResponseResult.Fail("加载配置项出错");
                }
                    //生成下一节点的审批记录
               await  NextNodeApproval(pointer,workflow, workflowDef,input,  options);

               
                workflow.LastModifierId = _currentUser.Id;
                workflow.Reference = _currentUser.Id.ToString();
               await _workflowRepos.UpdateAsync(workflow);

                return ResponseResult.Success(string.Empty);
            }
            catch (Exception ex)
            {
                return ResponseResult.Fail(ex.Message);
            }
        }
        /// <summary>
        /// 根据当前节点获取下一节点
        /// </summary>
        /// <param name="currentNode"></param>
        /// <returns></returns>
        //private string GetNextNodeKey(PersistedWorkflow workflow,WorkflowNode currentNode, WorkflowAuditInput input)
        //{
            
                

        //}
        private async Task NextNodeApproval(PersistedExecutionPointer pointer, PersistedWorkflow workflow, PersistedWorkflowDefinition def, WorkflowAuditInput input, BaseApprovalOption option)
        {
            var currentNode = def.Nodes.Where(a => a.Key == pointer.EventKey).FirstOrDefault();
            var nextNodeKey = new NodeProcessor(workflow, currentNode, input,pointer,option).GetNextNodeKey();


            //更新待审批记录
            var currentUserAuditList = await _auditorRepos.GetListAsync(u => u.ExecutionPointerId == pointer.Id && u.WorkflowId == workflow.Id
                   && u.Status == EnumAuditStatus.UnAudited && u.UserId == _currentUser.Id);
                foreach (var item in currentUserAuditList)
                {
                    item.Status =input.Pass? EnumAuditStatus.Pass:EnumAuditStatus.Refuse;
                    item.Remark = input.Remark;
                    item.AuditTime = DateTime.Now;
                    workflow.LastModifierId = _currentUser.Id;
                    workflow.Reference = _currentUser.Id.ToString();
                }
                await _auditorRepos.UpdateManyAsync(currentUserAuditList);
           
                          
               



            if (nextNodeKey == null)
            {
             workflow.Status = WorkflowStatus.Complete;
            }else
            {
               
               
                if (!WorkFlowConfig.OrderOption.IsMultipleApproval )
                {
                    var auditList = await _auditorRepos.GetListAsync(u => u.ExecutionPointerId == pointer.Id && u.WorkflowId == workflow.Id && u.Status == EnumAuditStatus.UnAudited && u.UserId != _currentUser.Id);
                    if (auditList.Any())
                    {
                        foreach (var item in auditList)
                        {
                            item.Status = input.Pass ? EnumAuditStatus.Pass : EnumAuditStatus.Refuse;
                            item.Remark = $"系统自动处理:用户{_currentUser.UserName}已审";
                            item.AuditTime = DateTime.Now;
                            workflow.LastModifierId = _currentUser.Id;
                            workflow.Reference = _currentUser.Id.ToString();
                        }
                        await _auditorRepos.UpdateManyAsync(auditList);
                    }
                    //更新当前审批节点记录
                    pointer.Status = PointerStatus.Complete;
                    pointer.EndTime = DateTime.Now;
                    var nextNode = def.Nodes.Where(a => a.Key == nextNodeKey).FirstOrDefault();
                    //生成审批的节点
                    string nextPointerId = GuidGenerator.Create().ToString();
                    PersistedExecutionPointer nextPointer = new PersistedExecutionPointer(nextPointerId)
                    {
                        WorkflowId = workflow.Id,
                        StartTime = DateTime.Now,
                        StepId = 2,
                        Active = true,
                        EventName = nextNode?.Title,
                        EventKey = nextNode?.Key,
                        SourceKey=currentNode.Key,
                        SourceName=currentNode.Title,
                        EventPublished = true,
                        StepName = nextNode?.Title,
                        RetryCount = 0,
                        // PredecessorId = _currentUser?.Id.ToString(),
                        Status = PointerStatus.Running


                    };


                    //查找下一节点要审批的人员
               
                    var stepBodyName = nextNode.StepBody.Name;

                   var userList= _userAppService.GetApprovalUserList(nextNode, workflow).Result;
                    //生成待审批记录
                    List<PersistedWorkflowAuditor> auditorList = new List<PersistedWorkflowAuditor>();
                    foreach (var user in userList)
                    {
                        PersistedWorkflowAuditor audit = new PersistedWorkflowAuditor(GuidGenerator.Create().ToString())
                        {
                            WorkflowId = workflow.Id,
                            ExecutionPointerId = nextPointerId,
                            Status = nextNode.Title == OperateNameEnum.结束.ToString() ? EnumAuditStatus.Pass : EnumAuditStatus.UnAudited,

                            UserId = user.Id,
                            TenantId = workflow.TenantId,
                            UserIdentityName = user.Name,
                            CreationTime = DateTime.Now,
                            Remark = nextNode.Title == OperateNameEnum.结束.ToString() ? "结束" : string.Empty,
                            CreatorId = _currentUser?.Id,
                        };
                        auditorList.Add(audit);
                    }


                    //如果节点为自动审批则
                    if (stepBodyName == "FixedAutoAudit" && nextNode.Title == OperateNameEnum.结束.ToString())
                    {
                        var autoUser = await _userService.WfGetAsyncById(_currentUser.Id.Value);
                        userList.Add(autoUser);

                        PersistedWorkflowAuditor audit = new PersistedWorkflowAuditor(GuidGenerator.Create().ToString())
                        {
                            WorkflowId = workflow.Id,
                            ExecutionPointerId = nextPointerId,
                            Status = EnumAuditStatus.Pass,

                            UserId = autoUser.Id,
                            TenantId = workflow.TenantId,
                            UserIdentityName = autoUser.Name,
                            CreationTime = DateTime.Now,
                            Remark = "结束",
                            CreatorId = _currentUser?.Id,
                        };
                        auditorList.Add(audit);
                        nextPointer.StartTime = DateTime.Now;
                        nextPointer.EndTime = DateTime.Now;
                        nextPointer.StepId = 2;
                        nextPointer.Active = true;
                        nextPointer.EventName = nextNode?.Title;
                        nextPointer.EventKey = nextNode?.Key;
                        nextPointer.EventPublished = true;
                        nextPointer.StepName = nextNode?.Title;
                        nextPointer.RetryCount = 0;
                        nextPointer.EndTime = DateTime.Now;
                        nextPointer.PredecessorId = autoUser?.Id.ToString();
                        nextPointer.Status = PointerStatus.Complete;


                        workflow.Status = WorkflowStatus.Complete;
                        //await  NextNodeApproval(nextPointer, workflow, def, input).ConfigureAwait(true);
                    }
                    await _pointerRepos.InsertAsync(nextPointer);
                    await _auditorRepos.InsertManyAsync(auditorList);
                }
                
            }

            pointer.PredecessorId = _currentUser?.Id.ToString();
            await _pointerRepos.UpdateAsync(pointer);


        }

        public async Task<ResponseResult> AuditAsync_old(WorkflowAuditInput input)
        {
            try
            {
                var entity = await _auditorRepos.FirstOrDefaultAsync(u => u.ExecutionPointerId == input.ExecutionPointerId && u.UserId == _currentUser.Id);
                if (entity == null)
                {
                    return ResponseResult.Fail("不需要您审核");
                }

                var workflow = await _workflowRepos.FirstOrDefaultAsync(s => s.Id == entity.WorkflowId);
                if (workflow == null)
                {
                    return ResponseResult.Fail("流程不存在");
                }

                string oldValue = !input.Pass ? "$approved_pass" : "$approved_reject";
                string newValue = input.Pass ? "$approved_pass" : "$approved_reject";
                workflow.Data = workflow.Data.Replace(oldValue, newValue);
                //WorkflowData businessData = JsonConvert.DeserializeObject<WorkflowData>(workflow?.Data);
                //string isApproved = input.Pass ? "$approved_pass" : "$approved_reject";
                //businessData.IsApproved = isApproved;
                //workflow.Data = JsonConvert.SerializeObject(businessData);

                //var user = await _currentUser(AbpSession.UserId.Value);
                //entity.Status = input.Pass ? EnumAuditStatus.Pass : EnumAuditStatus.Pass;
                entity.Status = input.Pass ? EnumAuditStatus.Pass : EnumAuditStatus.Refuse;
                entity.Remark = input.Remark;
                entity.AuditTime = DateTime.Now;

                
                workflow.LastModifierId = _currentUser.Id;
                workflow.Reference = _currentUser.Id.ToString();
                await _auditorRepos.UpdateAsync(entity, true);
                await _workflowRepos.UpdateAsync(workflow, true);

                //将覆节点其他待审核失效 避免需要多人审核
                var list = await _auditorRepos.GetListAsync(u => u.ExecutionPointerId == input.ExecutionPointerId
                      && u.Status == EnumAuditStatus.UnAudited && u.UserId != _currentUser.Id);
                list.ForEach(s =>
                {
                    //s.Status = EnumAuditStatus.Pass;
                    s.Status = input.Pass ? EnumAuditStatus.Pass : EnumAuditStatus.Refuse;
                    s.Remark = "失效多角色审核其他待审核记录";
                    s.AuditTime = DateTime.Now;
                    s.IsDeleted = true;
                });
                await _auditorRepos.UpdateManyAsync(list, true);
                //如果存在已审核的节点，则生成下一节点
                //if (!await _auditorRepos.AnyAsync(u => u.ExecutionPointerId == input.ExecutionPointerId
                //    && u.Status == EnumAuditStatus.Unapprove))
                if (!await _auditorRepos.AnyAsync(u => u.ExecutionPointerId == input.ExecutionPointerId
            && u.Status == EnumAuditStatus.UnAudited))
                {
                    var pointer = await _abpWorkflowManager.GetPersistedExecutionPointer(input.ExecutionPointerId);
                    await _abpWorkflowManager.PublishEventAsync(pointer.EventName, pointer.EventKey, pointer.EventData);
                }
                //entity.Status = input.Pass ? EnumAuditStatus.Pass : EnumAuditStatus.Refuse;
                //await _auditorRepos.UpdateAsync(entity, true);
                return ResponseResult.Success(string.Empty);
            }
            catch (Exception ex)
            {
                return ResponseResult.Fail(ex.Message);
            }
        }

        /// <summary>
        /// 终止流程
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        /// 
      [UnitOfWork]
        public async Task<ResponseResult> TerminateAsync(TerminateWorkflow input)
        {
            try
            {
                var workflow = await _workflowRepos.FirstOrDefaultAsync(a => a.Id == input.WorkflowId);
                if (workflow == null)
                {
                    return ResponseResult.Fail("流程终止失败,原因：流程不存在！");
                }
                var auditList = (await _auditorRepos.GetQueryableAsync()).Where(a => a.UserId == _currentUser.Id && a.Status == EnumAuditStatus.UnAudited && a.WorkflowId == workflow.Id).ToList();
                if (!auditList.Any())
                {
                    return ResponseResult.Fail("当前流程不需要您审批！");
                }
                workflow.Status = WorkflowStatus.Terminated;
                foreach (var item in auditList)
                {
                    item.Status = EnumAuditStatus.Unapprove;
                    item.Remark = input.Remark;
                    item.UserId = _currentUser.Id.Value;
                    item.UserIdentityName = _currentUser.Name;
                    item.AuditTime = DateTime.Now;
                   
                }
                var poinerId = auditList.FirstOrDefault().ExecutionPointerId;
                var poiner = await _pointerRepos.FirstOrDefaultAsync(a => a.Id == poinerId);
                if(poiner != null)
                {
                    poiner.PredecessorId = _currentUser?.Id.ToString();
                    poiner.Status = PointerStatus.Complete;
                }
                await _pointerRepos.UpdateAsync(poiner);
                await _workflowRepos.UpdateAsync(workflow);
                await _auditorRepos.UpdateManyAsync(auditList);
                return ResponseResult.Success("操作成功");
            }
            catch (Exception ex)
            {
                return ResponseResult.Fail($"流程终止失败，原因：{ex.Message}");
            }

            
        }
        public async Task<ResponseResult> TerminateAsync_old(string workflowId)
        {
            var result = await _abpWorkflowManager.TerminateWorkflow(workflowId);
            if (result) return ResponseResult.Success("流程已经终止");
            else return ResponseResult.Fail("流程终止失败");
        }

        /// <summary>
        /// 根据业务id进行审核
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<ResponseResult> AuditByBusinessIdAsync(WorkflowAuditByBusinessIdInput input)
        {
            //根据业务ID获取流程信息
            string bus = string.Format($"\"businessId\":\"{input.BusinessId}\"");
            var workflow = await _workflowRepos.FirstOrDefaultAsync(s => s.Status == WorkflowStatus.Runnable && s.WorkflowDefinitionId == input.WfdefId && s.Data.Contains(bus));
            if (workflow == null)
            {
                return ResponseResult.Fail("流程不存在");
            }
            var entity = await _auditorRepos.FirstOrDefaultAsync(u => u.WorkflowId == workflow.Id && u.UserId == _currentUser.Id && u.Status == EnumAuditStatus.UnAudited);
            if (entity == null)
            {
                return ResponseResult.Fail("不需要您审核");
            }

            entity.Status = input.Pass ? EnumAuditStatus.Pass : EnumAuditStatus.Pass;
            entity.Remark = input.Remark;
            entity.AuditTime = DateTime.Now;

            string oldValue = !input.Pass ? "$approved_pass" : "$approved_reject";
            string newValue = input.Pass ? "$approved_pass" : "$approved_reject";
            workflow.Data = workflow.Data.Replace(oldValue, newValue);
            workflow.LastModifierId = _currentUser.Id;
            workflow.Reference = _currentUser.Id.ToString();
            await _auditorRepos.UpdateAsync(entity, true);
            await _workflowRepos.UpdateAsync(workflow, true);

            //将覆节点其他待审核失效 避免需要多人审核
            var list = await _auditorRepos.GetListAsync(u => u.ExecutionPointerId == entity.ExecutionPointerId
                  && u.Status == EnumAuditStatus.UnAudited && u.UserId != _currentUser.Id);
            list.ForEach(s =>
            {
                s.Status = EnumAuditStatus.Pass;
                s.Remark = "失效多角色审核其他待审核记录";
                s.AuditTime = DateTime.Now;
                s.IsDeleted = true;
            });
            await _auditorRepos.UpdateManyAsync(list, true);

            //如果存在已审核的节点，则生成下一节点
            if (!await _auditorRepos.AnyAsync(u => u.ExecutionPointerId == entity.ExecutionPointerId
                && u.Status == EnumAuditStatus.Unapprove))
            {
                var pointer = await _abpWorkflowManager.GetPersistedExecutionPointer(entity.ExecutionPointerId);
                await _abpWorkflowManager.PublishEventAsync(pointer.EventName, pointer.EventKey, pointer.EventData);
            }
            entity.Status = input.Pass ? EnumAuditStatus.Pass : EnumAuditStatus.Refuse;
            await _auditorRepos.UpdateAsync(entity, true);
            return ResponseResult.Success(string.Empty);
        }

        /// <summary>
        /// 获取单据待审核节点信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<ResponseResult<GetMyAuditPageListOutput>> GetAuditInfoAsync(GetAuditInfoInput input)
        {
            //根据业务ID获取流程信息
            string bus = string.Format($"\"businessId\":\"{input.BusinessId}\"");
            var workflow = await _workflowRepos.FirstOrDefaultAsync(s => s.Status == WorkflowStatus.Runnable && s.WorkflowDefinitionId == input.WfdefId && s.Data.Contains(bus));
            if (workflow == null)
            {
                return ResponseResult<GetMyAuditPageListOutput>.Success(string.Empty, new GetMyAuditPageListOutput());
            }
            var result = await (await _auditorRepos.GetQueryableAsync()).Where(u => u.WorkflowId == workflow.Id && u.UserId == _currentUser.Id && u.Status == EnumAuditStatus.UnAudited)
                .Select(u => new GetMyAuditPageListOutput
                {
                    Id = u.Id,
                    //ExecutionPointerId = u.ExecutionPointerId,
                    CreationTime = u.CreationTime,
                    Title = u.Workflow.Description,
                    UserName = u.UserIdentityName,
                    WorkflowDefinitionId = u.Workflow.WorkflowDefinitionId,
                    Version = u.Workflow.WorkflowDefinition.Version,
                    WorkflowId = u.WorkflowId,
                    Status = u.Status,
                    AuditTime = u.AuditTime,
                    CreatorId = u.CreatorId ?? Guid.Empty,
                    //CurrentStepName = u.ExecutionPointer.StepName,
                    BusinessData = JsonConvert.DeserializeObject<WorkflowData>(u.Workflow.Data),
                    CreatorName = u.Workflow.CreateUserIdentityName,
                    IsApproval = u.UserId == _currentUser.Id,
                    Nodes = u.Workflow.WorkflowDefinition.Nodes,
                }).FirstOrDefaultAsync();
            return ResponseResult<GetMyAuditPageListOutput>.Success(string.Empty, result);
        }
    }
}
